package com.lightsaber.trade.as.service.category.impl;

import java.util.List;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.lightsaber.trade.as.dao.category.CategoryLeafDao;
import com.lightsaber.trade.as.dao.category.CategoryNodeDao;
import com.lightsaber.trade.as.dao.category.CategoryOwnerDao;
import com.lightsaber.trade.as.entity.category.Category;
import com.lightsaber.trade.as.entity.category.CategoryBranch;
import com.lightsaber.trade.as.entity.category.CategoryLeaf;
import com.lightsaber.trade.as.entity.category.CategoryNode;
import com.lightsaber.trade.as.entity.category.CategoryOwner;
import com.lightsaber.trade.as.entity.planning.PlanningStatus;
import com.lightsaber.trade.as.service.category.CategoryNodeService;
import com.lightsaber.trade.as.service.category.CategoryOwnerService;
import com.lightsaber.trade.as.service.category.CategoryProgrammeAttributeService;
import com.lightsaber.trade.as.service.category.CategoryService;
import com.lightsaber.trade.core.common.util.CurrentUser;
import com.lightsaber.trade.core.entity.AuditedObject;
import com.lightsaber.trade.core.entity.BaseEntity;

@Component
@Service
@Transactional
public class CategoryOwnerServiceImpl implements CategoryOwnerService {
    @Autowired
    CategoryOwnerDao categoryOwnerDao;
    @Autowired
    CategoryNodeDao categoryNodeDao;
    @Autowired
    CategoryService categoryService;
    @Autowired
    CategoryNodeService categoryNodeService;
    @Autowired
    CategoryLeafDao categoryLeafDao;
    @Autowired
    CategoryProgrammeAttributeService attService;

    @Override
    public void create(final CategoryOwner categoryOwner) {
        categoryOwnerDao.save(categoryOwner);

    }

    @Override
    public CategoryOwner findById(final String id) {

        return null;
    }

    @Override
    public void deleteById(final String id) {
        categoryOwnerDao.delete(id);

    }

    @Override
    public void saveByCategoryNodeAndRoleCodes(final String categoryNodeId,
            final List<String> roleCodes) throws Exception {

        CategoryNode categoryNode = categoryNodeDao.load(categoryNodeId);
        List<CategoryOwner> list = findByCategoryNodeId(categoryNodeId);

        if (roleCodes == null || roleCodes.isEmpty()) {
            List<Category> categoryList = categoryNode.getOwnedBranchTrees();
            if (categoryList.isEmpty()) {
                deleteByCategoryNodeId(categoryNodeId);
                return;
            } else {
                throw new Exception(
                        "Some Branch Trees are under this Node, so you cann't uncheck all Owners.");
            }
        } else {
            deleteByCategoryNodeId(categoryNodeId);
        }

        for (String roleCode : roleCodes) {
            CategoryOwner categoryOwner = new CategoryOwner();
            categoryOwner.setCategoryNode(categoryNode);
            categoryOwner.setRoleCode(roleCode);
            categoryOwnerDao.save(categoryOwner);
        }
        if (list.isEmpty() && categoryNode.getCategory() == null) {
            generalOwnerTree(categoryNodeId);
        }
    }

    @Override
    public void generalOwnerTree(final String categoryNodeId) throws Exception {
        CategoryNode oldCategoryNode = categoryNodeDao.load(categoryNodeId);
        Category oldCategory = getRootCategoryByCategoryNode(oldCategoryNode);

        // create category
        Category newCategory = new Category();
        BeanUtils.copyProperties(oldCategory, newCategory, new String[] { BaseEntity.ID,
                BaseEntity.VERSION, AuditedObject.CREATED_BY, AuditedObject.CREATED_DATE,
                "level1Planning", "root", "ownerNode", "planningList", "archivedImageList" });
        newCategory.setBranchName(oldCategoryNode.getName());
        newCategory.setOwnerNode(oldCategoryNode);
        categoryService.save(newCategory);

        // create branch tree root node
        if (oldCategoryNode.getIsLeafNode() == 0) {
            CategoryNode newCategoryNode = new CategoryBranch();

            // BeanUtils.copyProperties(oldCategoryNode, newCategoryNode, new
            // String[] { BaseEntity.ID,
            // BaseEntity.VERSION, "parent", "category",
            // AuditedObject.CREATED_BY, AuditedObject.CREATED_DATE,
            // "categoryOwners", "categoryPlanners", "children",
            // "ownedBranchTrees" });

            BeanUtils.copyProperties(oldCategoryNode, newCategoryNode, new String[] {
                    BaseEntity.ID, BaseEntity.VERSION, "parent", "category",
                    AuditedObject.CREATED_BY, AuditedObject.CREATED_DATE, "categoryOwners",
                    "categoryPlanners", "children", "ownedBranchTrees", "categoryPlanningItems" });

            newCategoryNode.setCategory(newCategory);
            categoryNodeService.saveRoot(newCategoryNode);

        } else {
            CategoryLeaf newCategoryLeaf = new CategoryLeaf();

            CategoryLeaf oldCategoryLeaf = categoryLeafDao.get(oldCategoryNode.getId());

            BeanUtils.copyProperties(oldCategoryLeaf, newCategoryLeaf, new String[] {
                    BaseEntity.ID, BaseEntity.VERSION, "parent", "category",
                    AuditedObject.CREATED_BY, AuditedObject.CREATED_DATE, "categoryOwners",
                    "categoryPlanners", "children", "ownedBranchTrees",
                    "categoryProgrammeAttributes", "categoryPlanningItems", "selectedPhraseOuts" });

            newCategoryLeaf.setCategory(newCategory);
            newCategoryLeaf.setIsInheritParentNode(0);
            categoryNodeService.saveLeaf(newCategoryLeaf);

            attService.copyAttributeByCategoryNode(oldCategoryLeaf, newCategoryLeaf);

        }

    }

    public Category getRootCategoryByCategoryNode(CategoryNode categoryNode) {
        while (categoryNode.getParent() != null) {
            categoryNode = categoryNode.getParent();
        }
        return categoryNode.getCategory();
    }

    @Override
    public void deleteByCategoryNodeId(final String categoryNodeId) {
        categoryOwnerDao.deleteByCategoryNodeId(categoryNodeId);
    }

    @Override
    public List<CategoryOwner> findByCategoryNodeId(final String categoryNodeId) {
        return categoryOwnerDao.findByCategoryNodeId(categoryNodeId);
    }

    public List<Category> findCategoryOwedToCurrentUser() {
        // CurrentUser.get();

        return null;
    }

}
